home *** CD-ROM | disk | FTP | other *** search
- /* ------------------------------------------------------------------
- MML compiler [M2]
- programmed by S.Yamamoto (SHINNOSUKE)
- m2pre.c -- pre process source
- ------------------------------------------------------------------ */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include "m2.h"
-
- #define SUCCSESS 0
- #define FAILURE (-1)
- #define TRUE 1
- #define FALSE 0
- #define ERR (-1)
- #define YES 1
- #define NO 0
-
- #define FILENEST 8 /* #include の入れ子レベル */
- #define IFNEST 8 /* #if(n)def の入れ子レベル */
- #define MACRO_MAX 1024 /* 同時に定義できるマクロ数 */
- #define MACNAME_MAX 31 /* マクロ名の有効文字数 */
- #define MACDAT_MAX 255 /* マクロデータの最大長 */
- #define LOOP_MAX 16 /* for next のレベル */
- #define CONDITION_MAX 8 /* 条件コンパイルのレベル */
- #define RDLEN_MAX 509 /* ソース行の最高文字数(バイト) */
- #define WTLEN_MAX 4096 /* 処理後の文字数(バイト) */
-
- typedef struct {
- FILE *fpi;
- char name[FILENAME_MAX];
- unsigned int line;
- } FILEST;
-
- FILEST fileStack[FILENEST];
-
- typedef struct {
- int line;
- long int offset;
- int count;
- } LOOP;
-
- LOOP loopStack[LOOP_MAX];
-
- typedef struct {
- char flag;
- char *name; /* マクロ名 */
- char *data; /* データ */
- } MACRO;
-
- MACRO macroStack[MACRO_MAX];
-
- int comment; /* コメントネスト */
- int fileNest; /* ファイル */
- int condNest; /* 条件 */
- int loopNest; /* ループ */
- int condition[CONDITION_MAX]; /* 条件 */
- int macCount; /* マクロ数 */
-
- char readBuf[RDLEN_MAX]; /* 読み込みバッファ */
- char writeBuf[WTLEN_MAX]; /* 書き込みバッファ */
-
- char macPara[64] = { 0 }; /* マクロ用パラメータ */
-
- /* エラー定義 */
- char *MSG_cntopn = "Can't open file '%s'\n";
- char *MSG_cntcrt = "Can't creat file '%s'\n";
- char *MSG_cntwrt = "Can't open file '%s'\n";
- char *MSG_cntalc = "Can't allocate memory (%s)\n";
- char *MSG_misopd = "Missing operand (%s)\n";
- char *MSG_miscmt = "Missing comment\n";
- char *MSG_undmac = "Undefined '%s' macro\n";
- char *MSG_undmml = "Undefined this MML '%s'\n";
- char *MSG_undctl = "Undefined this control\n";
- char *MSG_undstm = "Undefined this statement\n";
- char *MSG_illfnc = "Illgel function call %s\n";
- char *MSG_toonst = "%s too nested\n";
- char *MSG_toodfn = "Too defined\n";
- char *MSG_syntax = "Syntax error (%s)\n";
- char *MSG_outwka = "Out of work-area\n";
- char *MSG_lbover = "Line buffer overflow\n";
- char *MSG_fndsmc = "Already defined '%s' macro\n";
- char *MSG_unperr = "Unprintable error\n";
- char *MSG_looper = "#next without #for\n";
- char *MSG_cdcomp = "#else/#endif without #if(n)def\n";
- char *MSG_freerr = "%s\n";
- char *MSG_errdtv = "Error directive: %s\n";
-
- int errMsg( char *s1,char *s2 ) /* エラー処理 */
- {
- char buf[255];
-
- if( s1 != NULL ) {
- if( s2 != NULL )
- sprintf( buf ,s1 ,s2 );
- else strcpy( buf ,s1 );
- printf( "%s:%d:%s\n" ,fileStack[fileNest].name
- ,fileStack[fileNest].line ,buf );
- }
- exit( EXIT_FAILURE );
- }
-
- char *lineGet( void ) /* 一行読み込む */
- {
- for(;;) {
- fileStack[fileNest].line++;
- if( fgets( readBuf ,RDLEN_MAX ,fileStack[fileNest].fpi ) == NULL ) {
- fclose( fileStack[fileNest].fpi );
- if( --fileNest < 0 ) return( NULL );
- }
- else break;
- }
- return( readBuf );
- }
-
- int delComment( void ) /* コメントを取り拡張表記をスペースに */
- {
- char *rp;
- char *wp;
- char dat;
-
- rp = &readBuf[0];
- wp = rp;
- while( *rp != '\0' ) {
- if( *rp == '/' && *(rp+1) == '*' ) {
- comment++;
- rp += 2;
- continue;
- }
- if( *rp == '*' && *(rp+1) == '/' ) {
- comment--;
- rp += 2;
- if( comment < 0 )
- errMsg( MSG_miscmt ,NULL );
- continue;
- }
- if( comment == 0 ) {
- if( *rp == '/' && *(rp+1) == '/' )
- break;
- dat = *rp;
- rp++;
- if( dat == '\n' ) continue;
- *wp = ( dat >= '\a' && dat <= '\r' )?' ':dat;
- wp++;
- }
- else rp++;
- }
- *wp = '\0';
- return( SUCCSESS );
- }
-
- /* マクロ処理サブ */
-
- int macCheck( char *s ) /* マクロの存在を確かめる */
- {
- int i;
- int ret = ERR;
-
- if( macCount == 0)
- return( ERR );
- for( i=0;i<macCount;i++ ) {
- if( strcmp( s ,macroStack[i].name ) == 0) {
- ret = i;
- break;
- }
- }
- return( ret ); /* [RET] macNumber=found ERR=not found */
- }
-
- int macSort( void ) /* 長いマクロ名順にソート(基本選択法)*/
- {
- int i;
- int j;
- int s;
- int max;
- int chk;
-
- MACRO dummy;
-
- if( macCount <= 1 )
- return(SUCCSESS);
-
- for( i=0;i<macCount-1;i++ ) {
- max = strlen( macroStack[i].name );
- s = i;
- for( j=i+1;j<macCount;j++ ) {
- chk = strlen( macroStack[j].name );
- if( chk > max ){
- max = chk;
- s = j;
- }
- }
- dummy = macroStack[i];
- macroStack[i] = macroStack[s];
- macroStack[s] = dummy;
- }
- return( SUCCSESS );
- }
-
- int macExpand( char *wp ) /* マクロ展開 */
- {
- char *s1;
- char *s2;
- char *s3;
- char *msg = "Macro para error";
-
- int i;
- int ln;
- int ld;
- int n = ERR;
-
- if( strncmp( wp+1 ,"_PARA_" ,6 ) == 0 ) {
- ln = 6;
- ld = strlen( macPara );
- s1 = wp + 1 + ln;
- s2 = wp + ld;
- memmove( s2 ,s1 ,strlen( wp )-ln );
- memcpy( wp ,macPara ,ld );
- return( 0 );
- }
-
- for( i=0;i<macCount;i++ ) {
- ln = strlen( macroStack[i].name );
- if( strncmp( wp+1 ,macroStack[i].name ,ln ) == 0) {
- n = i;
- break;
- }
- }
-
- if( n == ERR )
- return(1);
-
- ld = strlen( macroStack[n].data );
- s1 = wp + 1 + ln;
- s2 = wp + ld;
-
- memmove( s2 ,s1 ,strlen(wp)-ln );
- memcpy( wp ,macroStack[n].data ,ld );
-
- if( macroStack[n].flag == TRUE )
- {
- s3 = s2;
- while( *s3 == ' ' )
- s3++;
-
- if( *s3 != '(' )
- errMsg( MSG_freerr ,msg );
- *s3 = ' ';
- s3++;
- i = 0;
- while( *s3 != ')' ) {
- if( i >= 63 )
- errMsg( MSG_freerr ,msg );
- macPara[i] = (*s3);
- *s3 = ' ';
- s3++;
- i++;
- }
- *s3 = ' ';
- macPara[i] = '\0';
- }
- return(0);
- }
-
- void macRepeat( char *wp ) /* リピート */
- {
- char *msg = "Repeat";
- char *s1;
- char *s2;
- char *buf1;
- char *buf2;
-
- int i;
- int dummy = 0;
- int num;
- int l1;
- int l2 = 1;
-
- s1 = wp + 2;
-
- for(;;) {
- if( *s1 == '\0' )
- errMsg( MSG_syntax ,msg );
- if( *s1 == '(' ) dummy++;
- if( *s1 == ')' ) dummy--;
- if( dummy < 0 ) {
- break;
- }
- s1++;
- l2++;
- }
- *s1 = '\0';
- s1++;
- num = strToInt( &s1 ,0 ,16 ,2 ,msg );
- l1 = strlen(s1) + 1;
-
- if(( buf1 = (char*)malloc( l1 )) == NULL )
- errMsg( MSG_cntalc ,msg );
- if(( buf2 = (char*)malloc( l2 )) == NULL)
- errMsg( MSG_cntalc ,msg );
- strcpy( buf1 ,s1 );
-
- s2 = wp + 2;
- strcpy( buf2 ,s2 );
-
- *wp = '\0';
- for( i=0;i<num;i++ )
- strcat(wp,buf2);
- strcat( wp ,buf1 );
-
- free( buf1 );
- free( buf2 );
- return;
- }
-
- /* 前処理指令 */
-
- int preInclude( char *p ) /* インクルードファイルのオープン */
- {
- char *msg = "#include";
- char *s1;
- char *s2;
-
- s1 = strchr( p ,'<' );
- if( s1 == NULL )
- errMsg( MSG_misopd ,msg );
- s2 = strchr( ++s1 ,'>' );
- if( s2 == NULL || s1 == s2 )
- errMsg( MSG_misopd ,msg );
- *s2 = '\0';
- if( ++fileNest >= FILENEST )
- errMsg( MSG_toonst ,msg );
- strncpy( fileStack[fileNest].name ,s1 ,FILENAME_MAX - 1 );
-
- fileStack[fileNest].line = 0;
- if(( fileStack[fileNest].fpi = fopen(fileStack[fileNest].name , "rt")) == NULL )
- errMsg( MSG_cntopn ,fileStack[fileNest].name );
- return( SUCCSESS );
- }
-
- int preDefine( char *p ) /* マクロ定義 */
- {
- char *msg = "#define";
- char *s;
- char mn[MACNAME_MAX + 1];
- char md[MACDAT_MAX + 1];
- char flag = FALSE;
-
- if( macCount >= MACRO_MAX )
- errMsg( MSG_toodfn ,NULL );
- if( *p == '&' ) {
- flag = TRUE;
- p++;
- }
-
- if( *p == '\0' )
- errMsg( MSG_misopd ,msg );
-
- s = strchr( p ,' ' );
- if( s != NULL ) {
- *s = '\0';
- strncpy( mn ,p ,MACNAME_MAX );
- *s = ' ';
- s = skipSpace( s );
- strncpy( md ,s ,MACDAT_MAX );
- }
- else {
- strncpy( mn ,p ,MACNAME_MAX );
- md[0] = '\0';
- }
- if( macCheck( mn ) != ERR )
- errMsg( MSG_fndsmc ,mn );
- if(( macroStack[macCount].name = malloc( strlen(mn)+1 )) == NULL )
- errMsg( MSG_cntalc ,"macro" );
- if(( macroStack[macCount].data = malloc( strlen(md)+1 )) == NULL )
- errMsg( MSG_cntalc ,"macro" );
-
- strcpy( macroStack[macCount].name ,mn );
- strcpy( macroStack[macCount].data ,md );
-
- macroStack[macCount].flag = flag;
- macCount++;
- macSort();
- return(SUCCSESS);
- }
-
- int preUndef( char *p ) /* マクロ解除 */
- {
- char *msg = "#undef";
- char *s;
- int n;
-
- if( *p == '\0' )
- errMsg( MSG_misopd ,msg );
- s = strchr( p ,' ' );
- if( s != NULL )
- *s = '\0';
- if(( n = macCheck( p )) == ERR )
- errMsg( MSG_undmac ,p );
-
- free( macroStack[n].name );
- free( macroStack[n].data );
- macCount--;
- if( macCount != 0 ) {
- macroStack[n] = macroStack[macCount];
- macSort();
- }
- return( SUCCSESS );
- }
-
- int preCondition( char *p ,int m ) /* 条件組み込み */
- {
- char *msg = "(conditional compile)";
- char *s;
- int n;
-
- if( m == 4 || m == 5 ) {
- if( condNest >= IFNEST )
- errMsg( MSG_toonst ,msg );
- if( *p == '\0' )
- errMsg( MSG_misopd ,msg );
- s = strchr( p ,' ' );
- if( s != NULL )
- *s = '\0';
- n = macCheck( p );
- }
- switch( m ) {
- case 4:
- if( n == ERR )
- condition[condNest] = 1;
- else condition[condNest] = 0;
- condNest++;
- break;
- case 5:
- if( n == ERR )
- condition[condNest] = 0;
- else condition[condNest] = 1;
- condNest++;
- break;
- case 6:
- if( condNest == 0 )
- errMsg( MSG_cdcomp ,NULL );
- condition[condNest-1] = ( condition[condNest-1] == 0 )?1:0;
- break;
- case 7:
- if( condNest == 0 )
- errMsg( MSG_cdcomp ,NULL );
- condNest--;
- break;
- }
- return( SUCCSESS );
- }
-
- int preForNext( char *p ,int n ) /* ループ */
- {
- int dummy;
-
- switch( n ) {
- case 8:
- if( loopNest >= LOOP_MAX )
- errMsg( MSG_toonst ,"#for/#next" );
- loopStack[loopNest].line = fileStack[fileNest].line;
- loopStack[loopNest].offset = ftell( fileStack[fileNest].fpi );
- loopStack[loopNest].count = strToInt( &p,1,256,0,NULL );
- loopNest++;
- break;
- case 9:
- if( loopNest == 0 )
- errMsg( MSG_looper ,NULL );
- dummy = loopNest - 1;
- loopStack[dummy].count--;
- if( loopStack[dummy].count >= 1 ) {
- fseek( fileStack[fileNest].fpi,loopStack[dummy].offset,SEEK_SET );
- fileStack[fileNest].line = loopStack[dummy].line;
- }
- else loopNest--;
- break;
- }
- return( SUCCSESS );
- }
-
- int preDirective( void ) /* 前処理指令メイン */
- {
- char *p;
-
- int n;
- int dummy;
-
- static char *preCommand[] = {
- "include",
- "define",
- "undef",
- "error",
- "ifdef",
- "ifndef",
- "else",
- "endif",
- "for",
- "next",
- "message",
- "\0"
- };
-
- p = skipSpace( &readBuf[1] );
- n = comSearch( preCommand ,p );
- if( n == ERR )
- errMsg( MSG_undstm ,NULL );
-
- p += strlen( preCommand[n] );
- p = skipSpace( p );
-
- if( n >=4 && n <= 7 ) {
- preCondition( p ,n );
- return( SUCCSESS );
- }
-
- dummy = ( condNest==0 )?0 :condition[condNest-1];
- if( dummy != 0)
- return( SUCCSESS );
-
- switch( n ) {
- case 0:
- preInclude( p );
- break;
- case 1:
- preDefine( p );
- break;
- case 2:
- preUndef( p );
- break;
- case 3:
- errMsg( MSG_errdtv ,p );
- break;
- case 8:
- case 9:
- preForNext( p ,n );
- break;
- case 10:
- printf( "%s\n" ,p );
- break;
- }
- return( SUCCSESS );
- }
-
- /* 前処理メイン関数 */
-
- int Pre_open( const char *fn ) /* ファイルオープン */
- {
- if(( fileStack[0].fpi = fopen( fn ,"rt" )) == NULL ) {
- printf( MSG_cntopn ,fn );
- errMsg( NULL,NULL );
- }
-
- comment = 0;
- fileNest = 0;
- condNest = 0;
- loopNest = 0;
- macCount = 0;
-
- strcpy( fileStack[0].name ,fn );
- fileStack[0].line = 0;
- return( SUCCSESS );
- }
-
- char *Pre_fgets( void ) /* 一行読み込み */
- {
- char *rp;
- char *wp;
- char *wb;
- int dummy;
-
- wb = &writeBuf[0];
-
- for(;;) {
- if( lineGet() == NULL )
- return( NULL );
- delComment(); /* コメントを取る */
-
- dummy = ( condNest == 0 ) ? 0 :condition[condNest-1];
- if( readBuf[0] != '#' && dummy == 0 )
- break;
- if( readBuf[0] == '#' )
- preDirective(); /* 前処理指令 */
- }
-
- rp = &readBuf[0];
- wp = wb;
- strcpy( wp ,rp );
-
- while( *wp != '\0' ) {
- if( *wp == '$' ) {
- if( *(wp+1) != '(' )
- wp += macExpand( wp );
- else macRepeat( wp );
- }
- else wp++;
- }
- return( wb );
- }
-